﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.Core.SocketCore.Models.DynamicObject
 * 唯一标识：ad1c07ba-2b29-4a97-8343-b6515109252e
 * 文件名：DynamicObject
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2024/8/12 21:54:49
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

using System.Collections.Concurrent;
using Vampirewal.Core.SocketCore.Extensions;

namespace Vampirewal.Core.SocketCore;

/// <summary>
/// 动态属性模型基类
/// </summary>
public class DynamicObject
{
    /// <summary>
    /// 构造函数
    /// </summary>
    public DynamicObject()
    {
    }

    /// <summary>
    /// 取值
    /// </summary>
    /// <typeparam name="TValue"></typeparam>
    /// <param name="dp"></param>
    /// <returns></returns>
    public TValue? GetValue<TValue>(DynamicProperty<TValue> dp)
    {
        return DynamicObject.Properties.TryGetValue(dp.Id, out var value) ? (TValue?)value : dp.Value;
    }

    /// <summary>
    /// 写值
    /// </summary>
    /// <typeparam name="TValue"></typeparam>
    /// <param name="dp"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public DynamicObject SetValue<TValue>(DynamicProperty<TValue> dp, TValue value)
    {
        if (DynamicObject.Properties.TryGetValue(dp.PropertyName, out var oldvalue))
        {
            if (DynamicObject.PropertyMetadataDic.TryGetValue(dp.PropertyName, out var propMetadata))
            {
                var prop = (propMetadata as DynamicPropertyMetadata<TValue>)!;

                prop.Callback?.Invoke(this, new DynamicPropertyChangedEventArgs<TValue>(dp, oldvalue, value));
            }
        }

        DynamicObject.Properties.AddOrUpdate(dp.Id, value);
        return this;
    }

    private static readonly ConcurrentDictionary<string, object?> Properties = new ConcurrentDictionary<string, object?>();

    private static readonly ConcurrentDictionary<string, object?> PropertyMetadataDic = new ConcurrentDictionary<string, object?>();

    /// <summary>
    /// 注册
    /// </summary>
    /// <param name="propertyName"></param>
    /// <param name="propertyMetadata"></param>
    /// <returns></returns>
    public static DynamicProperty<T> Register<T>(string propertyName, DynamicPropertyMetadata<T> propertyMetadata)
    {
        if (Properties.ContainsKey(propertyName))
        {
            throw new ArgumentException("属性名已被注册！");
        }

        var dp = new DynamicProperty<T>();
        dp.Id = Guid.NewGuid().ToString().Replace("-", "");
        dp.PropertyName = propertyName;
        dp.Value = propertyMetadata.DefaultValue;

        Properties.TryAdd(propertyName, propertyMetadata.DefaultValue);
        PropertyMetadataDic.TryAdd(propertyName, propertyMetadata);

        return dp;
    }
}